<template>
  <div class="earth-container">
    <div id="earth-canvas" ref="earthCanvas"></div>
    <div class="controls">
      <button @click="toggleRotation">{{ isRotating ? '暂停旋转' : '开始旋转' }}</button>
      <button @click="resetView">重置视角</button>
      <button @click="toggleGeoLayer">{{ showGeoLayer ? '隐藏地理区域' : '显示地理区域' }}</button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue'
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'

// 响应式变量
const earthCanvas = ref<HTMLElement | null>(null)
const isRotating = ref(true)
const showGeoLayer = ref(true)

// Three.js 变量
let scene: THREE.Scene
let camera: THREE.PerspectiveCamera
let renderer: THREE.WebGLRenderer
let earth: THREE.Mesh
let controls: OrbitControls
let animationId: number
let geoGroup: THREE.Group

// 初始化Three.js场景
const initScene = () => {
  // 创建场景
  scene = new THREE.Scene()
  scene.background = new THREE.Color(0x000000)

  // 创建相机
  camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
  )
  camera.position.z = 2

  // 创建渲染器
  renderer = new THREE.WebGLRenderer({ antialias: true })
  renderer.setSize(window.innerWidth, window.innerHeight)
  renderer.setPixelRatio(window.devicePixelRatio)
  earthCanvas.value?.appendChild(renderer.domElement)

  // 添加轨道控制器
  controls = new OrbitControls(camera, renderer.domElement)
  controls.enableDamping = true
  controls.dampingFactor = 0.05
  controls.enableZoom = true
  controls.minDistance = 1.2
  controls.maxDistance = 8

  // 创建地球
  createEarth()

  // 添加地理区域层
  createGeoLayer()

  // 添加光源
  addLights()

  // 添加星空背景
  createStarfield()
}

// 创建地球
function createEarth (){
  const geometry = new THREE.SphereGeometry(1.3, 64, 64)
  
  // 加载地球纹理
  const textureLoader = new THREE.TextureLoader()
//   const earthTexture = textureLoader.load('/src/assets/img/earth.jpg')
  const earthTexture = textureLoader.load(`${location.origin}/src/assets/img/earth.jpg`)
  const nightTexture = textureLoader.load(`${location.origin}/src/assets/img/earthNight.jpg`)
  
  // 创建材质
  const material = new THREE.MeshPhongMaterial({
    map: earthTexture,
    bumpScale: 0.05,
    specular: new THREE.Color('grey'),
    shininess: 3 // 广光照强度
  })

  earth = new THREE.Mesh(geometry, material)
  scene.add(earth)

  // 添加大气层效果
  //createAtmosphere()
}
// 创建地理区域层
const createGeoLayer = () => {
  geoGroup = new THREE.Group()
  
  // 加载地理数据
  fetch('/src/assets/json/worldGeoData.json')
    .then(response => {
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`)
      }
      return response.json()
    })
    .then(data => {
      console.log('地理数据加载成功:', data.features.length, '个国家')
      const features = data.features
      
      features.forEach((feature: any, index: number) => {
        const geometry = feature.geometry
        const properties = feature.properties
        const countryName = properties.name
        
        // 为每个国家生成随机颜色
        const color = new THREE.Color(
          Math.random() * 0.5 + 0.3,  // R: 0.3-0.8
          Math.random() * 0.5 + 0.3,  // G: 0.3-0.8
          Math.random() * 0.5 + 0.3   // B: 0.3-0.8
        )
        
        console.log(`处理国家: ${countryName}`)
        
        if (geometry.type === 'Polygon') {
          createCountryMesh(geometry.coordinates[0], color, countryName)
        } else if (geometry.type === 'MultiPolygon') {
          geometry.coordinates.forEach((polygon: any) => {
            createCountryMesh(polygon[0], color, countryName)
          })
        }
      })
      
      console.log('地理区域层创建完成，共添加了', geoGroup.children.length, '个国家')
      // 将地理区域层添加到场景
      earth.add(geoGroup)
    })
    .catch(error => {
      console.error('加载地理数据失败:', error)
      // 尝试使用相对路径
      console.log('尝试使用相对路径加载...')
      fetch('./src/assets/json/worldGeoData.json')
        .then(response => response.json())
        .then(data => {
          console.log('使用相对路径加载成功')
          // 重新处理数据
          const features = data.features
          features.forEach((feature: any) => {
            const geometry = feature.geometry
            const properties = feature.properties
            const countryName = properties.name
            const color = new THREE.Color(
              Math.random() * 0.5 + 0.3,
              Math.random() * 0.5 + 0.3,
              Math.random() * 0.5 + 0.3
            )
            
            if (geometry.type === 'Polygon') {
              createCountryMesh(geometry.coordinates[0], color, countryName)
            } else if (geometry.type === 'MultiPolygon') {
              geometry.coordinates.forEach((polygon: any) => {
                createCountryMesh(polygon[0], color, countryName)
              })
            }
          })
          earth.add(geoGroup)
        })
        .catch(err => {
          console.error('相对路径也失败:', err)
        })
    })
}

// 简化的球面多边形填充算法
function sphericalTriangulation(points: THREE.Vector3[]): number[] {
  if (points.length < 3) return []
  
  const vertices: number[] = []
  
  // 计算多边形的几何中心
  const center = new THREE.Vector3(0, 0, 0)
  points.forEach(point => {
    center.add(point)
  })
  center.divideScalar(points.length)
  center.normalize()
  center.multiplyScalar(1.3)
  
  // 创建从中心点到每个相邻顶点对的三角形
  for (let i = 0; i < points.length; i++) {
    const nextIndex = (i + 1) % points.length
    
    const p1 = center.clone()
    const p2 = points[i].clone()
    const p3 = points[nextIndex].clone()
    
    // 确保所有点都在球面上
    p1.normalize().multiplyScalar(1.3)
    p2.normalize().multiplyScalar(1.3)
    p3.normalize().multiplyScalar(1.3)
    
    vertices.push(
      p1.x, p1.y, p1.z,
      p2.x, p2.y, p2.z,
      p3.x, p3.y, p3.z
    )
  }
  
  return vertices
}

// 简化的耳切法（仅用于简单多边形）
function earClipping(points: THREE.Vector3[]): number[] {
  if (points.length < 3) return []
  
  const vertices: number[] = []
  
  // 对于球面多边形，使用更简单的方法
  // 直接使用扇形三角化，但添加额外的检查
  const center = new THREE.Vector3(0, 0, 0)
  points.forEach(point => {
    center.add(point)
  })
  center.normalize()
  center.multiplyScalar(1.3)
  
  // 创建从中心点到边界的三角形
  for (let i = 0; i < points.length - 1; i++) {
    vertices.push(
      center.x, center.y, center.z,
      points[i].x, points[i].y, points[i].z,
      points[i + 1].x, points[i + 1].y, points[i + 1].z
    )
  }
  
  return vertices
}

// 检查三点是否构成凸角
function isConvex(a: {x: number, y: number}, b: {x: number, y: number}, c: {x: number, y: number}): boolean {
  return ((c.x - a.x) * (b.y - a.y) - (b.x - a.x) * (c.y - a.y)) >= 0
}

// 检查点是否在三角形内
function pointInTriangle(p: {x: number, y: number}, a: {x: number, y: number}, 
                         b: {x: number, y: number}, c: {x: number, y: number}): boolean {
  const sign = (p1: {x: number, y: number}, p2: {x: number, y: number}, p3: {x: number, y: number}) => {
    return (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y)
  }
  
  const d1 = sign(p, a, b)
  const d2 = sign(p, b, c)
  const d3 = sign(p, c, a)
  
  const hasNeg = (d1 < 0) || (d2 < 0) || (d3 < 0)
  const hasPos = (d1 > 0) || (d2 > 0) || (d3 > 0)
  
  return !(hasNeg && hasPos)
}

// 创建国家网格
function createCountryMesh(coordinates: number[][], color: THREE.Color, countryName: string){
  try {
    const points: THREE.Vector3[] = []
    
    // 将经纬度坐标转换为3D球面坐标
    coordinates.forEach((coord: number[], index: number) => {
      const [lon, lat] = coord
      
      // 修正的球面坐标转换公式 - 添加调试信息
      // 将经纬度转换为弧度
      const phi = (90 - lat) * (Math.PI / 180)  // 纬度转换为极角
      
      // 尝试不同的经度偏移值，找到最匹配的
      let thetaOffset = -90  // 可以调整这个值：0, 90, -90, 180, -180
      const theta = (lon + thetaOffset) * (Math.PI / 180)
      
      // 调试输出第一个点的坐标
      if (index === 0 && countryName === 'China') {
        console.log(`调试 ${countryName} 第一个点:`, {
          原始坐标: [lon, lat],
          phi: phi,
          theta: theta,
          thetaOffset: thetaOffset
        })
      }
      
      // 使用与地球相同的半径
      const radius = 1.3  // 与地球半径保持一致
      
      // 球面坐标转直角坐标
      const x = radius * Math.sin(phi) * Math.cos(theta)
      const y = radius * Math.cos(phi)
      const z = radius * Math.sin(phi) * Math.sin(theta)
      
      points.push(new THREE.Vector3(x, y, z))
    })
    
    // 创建线条几何体
    const geometry = new THREE.BufferGeometry().setFromPoints(points)
    const material = new THREE.LineBasicMaterial({
      color: color,
      transparent: true,
      opacity: 0.8,
      linewidth: 2
    })
    
    const line = new THREE.Line(geometry, material)
    geoGroup.add(line)
    
    // 暂时移除填充以避免空洞问题，只保留边界线
    // 如果需要填充效果，可以考虑使用其他方法，如：
    // 1. 使用专业的地理可视化库
    // 2. 预处理地理数据为更好的格式
    // 3. 使用更复杂的球面三角化算法
    
    // 可选：添加点标记来显示边界
    if (points.length > 0) {
      const pointGeometry = new THREE.BufferGeometry()
      const pointPositions = new Float32Array(points.length * 3)
      
      points.forEach((point, i) => {
        pointPositions[i * 3] = point.x
        pointPositions[i * 3 + 1] = point.y
        pointPositions[i * 3 + 2] = point.z
      })
      
      pointGeometry.setAttribute('position', new THREE.BufferAttribute(pointPositions, 3))
      
      const pointMaterial = new THREE.PointsMaterial({
        color: color,
        size: 0.01,
        transparent: true,
        opacity: 0.6
      })
      
      const pointMesh = new THREE.Points(pointGeometry, pointMaterial)
      geoGroup.add(pointMesh)
    }
    
  } catch (error) {
    console.warn(`创建国家 ${countryName} 失败:`, error)
  }
}

// 创建大气层
function createAtmosphere(){
  const atmosphereGeometry = new THREE.SphereGeometry(1.4, 64, 64)
  const atmosphereMaterial = new THREE.MeshPhongMaterial({
    color: 0x4444ff,
    transparent: true,
    opacity: 0.1,
    side: THREE.BackSide
  })
  
  const atmosphere = new THREE.Mesh(atmosphereGeometry, atmosphereMaterial)
  earth.add(atmosphere)
}

// 添加光源
function addLights (){
  // 环境光
  const ambientLight = new THREE.AmbientLight(0x404040, 0.5)
  scene.add(ambientLight)

  // 方向光（模拟太阳光）
  const directionalLight = new THREE.DirectionalLight(0xffffff, 1)
  directionalLight.position.set(5, 3, 5)
  scene.add(directionalLight)

  // 点光源
  const pointLight = new THREE.PointLight(0xffffff, 0.5)
  pointLight.position.set(-5, -3, -5)
  scene.add(pointLight)
}

// 创建星空背景
function createStarfield() {
  const starsGeometry = new THREE.BufferGeometry()
  const starsMaterial = new THREE.PointsMaterial({
    color: 0xffffff,
    size: 0.02,
    transparent: true,
    opacity: 0.8
  })

  const starsVertices = []
  for (let i = 0; i < 10000; i++) {
    const x = (Math.random() - 0.5) * 2000
    const y = (Math.random() - 0.5) * 2000
    const z = (Math.random() - 0.5) * 2000
    starsVertices.push(x, y, z)
  }

  starsGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starsVertices, 3))
  const stars = new THREE.Points(starsGeometry, starsMaterial)
  scene.add(stars)
}

// 动画循环
function animate() {
  animationId = requestAnimationFrame(animate)

  // 地球自转
  if (isRotating.value && earth) {
    earth.rotation.y += 0.005
  }

  // 更新控制器
  controls.update()

  // 渲染场景
  renderer.render(scene, camera)
}

// 窗口大小调整
function handleResize() {
  if (!camera || !renderer) return
  
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()
  renderer.setSize(window.innerWidth, window.innerHeight)
}

// 控制函数
const toggleRotation = () => {
  isRotating.value = !isRotating.value
}

const resetView = () => {
  if (camera && controls) {
    camera.position.set(0, 0, 2)
    controls.reset()
  }
}

const toggleGeoLayer = () => {
  showGeoLayer.value = !showGeoLayer.value
  if (geoGroup) {
    geoGroup.visible = showGeoLayer.value
  }
}

// 生命周期钩子
onMounted(() => {
  initScene()
  animate()
  
  window.addEventListener('resize', handleResize)
})

onUnmounted(() => {
  if (animationId) {
    cancelAnimationFrame(animationId)
  }
  
  window.removeEventListener('resize', handleResize)
  
  // 清理Three.js资源
  if (renderer) {
    renderer.dispose()
  }
  
  if (earth) {
    earth.geometry.dispose()
    if (earth.material instanceof THREE.Material) {
      earth.material.dispose()
    }
  }
})
</script>

<style scoped>
.earth-container {
  position: relative;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}

#earth-canvas {
  width: 100%;
  height: 100%;
}

.controls {
  position: absolute;
  top: 20px;
  left: 20px;
  z-index: 100;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.controls button {
  padding: 10px 15px;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.3);
  color: white;
  border-radius: 5px;
  cursor: pointer;
  backdrop-filter: blur(10px);
  transition: all 0.3s ease;
}

.controls button:hover {
  background: rgba(255, 255, 255, 0.2);
  border-color: rgba(255, 255, 255, 0.5);
  transform: translateY(-2px);
}
</style>